﻿// YamlSurrogate.cs
//
// Copyright 2008 by Burt Harris
// Licensed under the Microsoft Public License (Ms-PL)
// See: http://www.codeplex.com/yaml/license
//
using System;
using System.Runtime.Serialization;
using System.Security.Permissions;

namespace YaTools.Yaml.Serialization
{

    /// <summary>
    /// Defines a serialization/deserialization strategy
    /// </summary>
    /// <remarks>
    /// Implementations of this abstract base might represent a generic strategy 
    /// (e.g. serializing an IEnumerable as a YAML sequence.) or be more tightly
    /// bound to a specific type (i.e. it might contain cached information about 
    /// the serializable members of a class).  
    /// 
    /// This could be defined as an interface, like ISerializationSurrogate, but 
    /// I honestly don't expect this functionalyity to be added existing classes.   
    /// Instead, it's been made to implement ISerializationSurrogate, to allow it
    /// to leverage the Surrogate Selector mechanism.   
    /// </remarks>
    /// 
    public abstract class YamlSurrogate : ISerializationSurrogate
    {
        // Retrieve URI representing a type serialized by this surrogate
        public virtual string GetUri(Type type)
        {
            return String.Concat(BaseUri.ToString(), StringFor(type));
        }

        /// <summary>
        /// Serialize data about an object (ISerializationSurrogate)
        /// </summary>
        /// <param name="obj">object/graph to serizlize</param>
        /// <param name="info">DO NOT USE, will be null</param>
        /// <param name="context">Context information, context.Context will be a YamlContext
        /// <remarks>
        /// YamlSurrogate's should cast context.Context to YamlContext and send the objects
        /// members to that Writer.   
        /// </remarks>

        [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        public abstract void GetObjectData(object obj, SerializationInfo info, StreamingContext context);

        /// <summary>
        /// Deserialize object from YAML 
        /// </summary>
        /// <param name="obj">object/graph to serizlize</param>
        /// <param name="info">DO NOT USE, will be null</param>
        /// <param name="context">Context information, context.Context will be a YamlContext
        /// <remarks>
        /// YamlSurrogate's should cast context.Context to YamlContext and send the objects
        /// members to that Writer.   
        /// </remarks>

        [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        
        public abstract object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector);

        // Base URI under for constructed URIs

        protected abstract Uri BaseUri { get; }

        /// <summary>
        /// Generate a string suitable for use in a URI for a specified type.
        /// </summary>
        /// <param name="type">The .NET type</param>
        /// <returns>String representing the type.  </returns>
        /// <remarks>
        /// While the returned string will be URIEscaped, things will look much better
        /// in the YAML file if we can arrange to encode types using just the URI 
        /// valid character set.
        /// </remarks>
        protected virtual string StringFor(Type type)
        {
            // TODO: better encoding...
            return type.FullName;
        }

    }

}
